﻿using PuppeteerSharp;
using PuppeteerSharp.Media;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;

namespace DzInfo.Tools.Web
{
    public class PdfGeneratorOptions
    {
        // 浏览器启动超时（毫秒）
        public int BrowserLaunchTimeout { get; set; } = 60000;

        // 导航超时（毫秒）
        public int NavigationTimeout { get; set; } = 60000;

        // 初始视口宽度
        public int InitialViewportWidth { get; set; } = 1920;

        // 初始视口高度
        public int InitialViewportHeight { get; set; } = 1080;

        // 额外加载时间（毫秒）
        public int ExtraLoadingTime { get; set; } = 8000;

        // 布局调整延迟（毫秒）
        public int LayoutAdjustmentDelay { get; set; } = 3000;

        // 自定义CSS样式
        public string CustomCss { get; set; } = @"
        <style>
            body, html {
                overflow: visible !important;
                width: auto !important;
                height: auto !important;
                margin: 0 !important;
                padding: 0 !important;
            }
            .dashboard-container, .chart-container, .data-grid {
                width: 100% !important;
                max-width: none !important;
                min-width: 0 !important;
                overflow: visible !important;
                box-sizing: border-box !important;
            }
        </style>";

        // 日志记录方法
        public Action<string> LogAction { get; set; } = Console.WriteLine;

        // 错误处理方法
        public Action<string, Exception> ErrorAction { get; set; } = (msg, ex) =>
        {
            Console.WriteLine(msg);
            Console.WriteLine(ex.StackTrace);
        };
    }
    public class PdfGenerator
    {
        private readonly PdfGeneratorOptions _options;

        public PdfGenerator(PdfGeneratorOptions options = null)
        {
            _options = options ?? new PdfGeneratorOptions();
        }

        public async Task GeneratePdfAsync(string url, string outputPath, string chromePath = null)
        {
            try
            {
                // 确保输出目录存在
                EnsureOutputDirectory(outputPath);

                // 设置浏览器选项
                var browserOptions = new LaunchOptions
                {
                    Headless = true,
                    Args = new[] {
                    "--no-sandbox",
                    "--disable-gpu",
                    "--disable-dev-shm-usage",
                    "--disable-setuid-sandbox"
                    },
                    Timeout = _options.BrowserLaunchTimeout,
                    IgnoredDefaultArgs = new[] { "--disable-extensions" }
                };

                // 处理Chrome路径
                if (!string.IsNullOrEmpty(chromePath) && File.Exists(chromePath))
                {
                    browserOptions.ExecutablePath = chromePath;
                    _options.LogAction?.Invoke($"使用系统Chrome: {chromePath}");
                }
                else
                {
                    // 使用内置Chromium
                    _options.LogAction?.Invoke("未提供有效Chrome路径，将使用内置Chromium...");

                    // 创建BrowserFetcher实例
                    var browserFetcher = new BrowserFetcher();

                    // 下载默认修订版本的Chromium
                    _options.LogAction?.Invoke("正在下载Chromium...");
                    var revisionInfo = await browserFetcher.DownloadAsync();

                    browserOptions.ExecutablePath = revisionInfo.GetExecutablePath();
                    _options.LogAction?.Invoke($"使用内置Chromium: {revisionInfo.GetExecutablePath()}");
                }
                AppDomain.CurrentDomain.AssemblyResolve += (sender, args) =>
                {
                    var name = new AssemblyName(args.Name);
                    if (name.Name == "System.Runtime.CompilerServices.Unsafe")
                    {
                        var a = typeof(System.Runtime.CompilerServices.Unsafe).Assembly;
                        return a;
                    }
                    return null;
                };
                _options.LogAction?.Invoke("正在启动浏览器...");
                using (var browser = await Puppeteer.LaunchAsync(browserOptions))
                {
                    _options.LogAction?.Invoke("浏览器已启动");

                    _options.LogAction?.Invoke("正在创建新页面...");
                    using (var page = await browser.NewPageAsync())
                    {
                        _options.LogAction?.Invoke("页面已创建");

                        // 设置初始视口
                        await page.SetViewportAsync(new ViewPortOptions
                        {
                            Width = _options.InitialViewportWidth,
                            Height = _options.InitialViewportHeight,
                            DeviceScaleFactor = 1
                        });

                        // 导航到目标URL
                        _options.LogAction?.Invoke($"正在导航到页面: {url}");
                        var navigationOptions = new NavigationOptions
                        {
                            WaitUntil = new[] { WaitUntilNavigation.Networkidle2 },
                            Timeout = _options.NavigationTimeout
                        };

                        await page.GoToAsync(url, navigationOptions);
                        _options.LogAction?.Invoke("页面导航完成");

                        // 应用自定义CSS
                        if (!string.IsNullOrEmpty(_options.CustomCss))
                        {
                            _options.LogAction?.Invoke("添加CSS优化...");
                            await page.AddStyleTagAsync(new AddTagOptions
                            {
                                Content = _options.CustomCss
                            });
                        }

                        // 等待额外时间确保内容加载
                        if (_options.ExtraLoadingTime > 0)
                        {
                            _options.LogAction?.Invoke($"等待额外时间确保内容加载 ({_options.ExtraLoadingTime}ms)...");
                            await Task.Delay(_options.ExtraLoadingTime);
                        }

                        // 动态获取页面尺寸
                        int pageWidth = await page.EvaluateFunctionAsync<int>(@"() => {
                        return document.documentElement.scrollWidth;
                    }");

                        int pageHeight = await page.EvaluateFunctionAsync<int>(@"() => {
                        return document.documentElement.scrollHeight;
                    }");

                        _options.LogAction?.Invoke($"页面实际尺寸: {pageWidth}px x {pageHeight}px");

                        // 调整视口以匹配内容
                        await page.SetViewportAsync(new ViewPortOptions
                        {
                            Width = pageWidth,
                            Height = pageHeight,
                            DeviceScaleFactor = 1
                        });

                        // 等待布局调整
                        if (_options.LayoutAdjustmentDelay > 0)
                        {
                            _options.LogAction?.Invoke($"等待页面布局调整 ({_options.LayoutAdjustmentDelay}ms)...");
                            await Task.Delay(_options.LayoutAdjustmentDelay);
                        }

                        // 保存截图用于调试
                        string screenshotPath = outputPath.Replace(".pdf", ".png");
                        _options.LogAction?.Invoke($"保存截图: {screenshotPath}");
                        await page.ScreenshotAsync(screenshotPath, new ScreenshotOptions
                        {
                            FullPage = true,
                            Type = ScreenshotType.Png
                        });
                        _options.LogAction?.Invoke("已保存页面截图用于调试");

                        // 生成PDF
                        _options.LogAction?.Invoke("生成PDF...");
                        var pdfOptions = new PdfOptions
                        {
                            PrintBackground = true,
                            Width = $"{Math.Ceiling(pageWidth / 96.0):F1}in",
                            Height = $"{Math.Ceiling(pageHeight / 96.0):F1}in",
                            Scale = 1m,
                            MarginOptions = new MarginOptions
                            {
                                Top = "0",
                                Right = "0",
                                Bottom = "0",
                                Left = "0"
                            },
                            PreferCSSPageSize = false
                        };

                        await page.PdfAsync(outputPath, pdfOptions);
                        _options.LogAction?.Invoke("PDF生成完成");
                    }
                }

                _options.LogAction?.Invoke($"PDF已成功保存至: {outputPath}");
            }
            catch (Exception ex)
            {
                _options.ErrorAction?.Invoke($"生成PDF失败: {ex.Message}", ex);
                throw;
            }
        }

        private void EnsureOutputDirectory(string outputPath)
        {
            try
            {
                var directory = Path.GetDirectoryName(outputPath);
                if (!Directory.Exists(directory))
                {
                    _options.LogAction?.Invoke($"创建输出目录: {directory}");
                    Directory.CreateDirectory(directory);
                }

                // 测试目录写入权限
                var testFile = Path.Combine(directory, "write_test.tmp");
                File.WriteAllText(testFile, "test");
                File.Delete(testFile);
            }
            catch (Exception ex)
            {
                _options.ErrorAction?.Invoke($"输出目录权限检查失败: {ex.Message}", ex);
                throw;
            }
        }
    }
}
